package com.hyt.it.ogt.ks.service.impl;


import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.ks.config.ConfigManager;
import com.hyt.it.ogt.ks.config.KsBizRunTimeException;
import com.hyt.it.ogt.ks.enums.*;
import com.hyt.it.ogt.ks.enums.log.CandidateAnswerLogType;
import com.hyt.it.ogt.ks.enums.log.LogEventType;
import com.hyt.it.ogt.ks.feign.model.Exam;
import com.hyt.it.ogt.ks.feign.model.ExamDTO;
import com.hyt.it.ogt.ks.model.entity.CandidateAnswer;
import com.hyt.it.ogt.ks.model.entity.CandidateLog;
import com.hyt.it.ogt.ks.model.entity.CandidatePaper;
import com.hyt.it.ogt.ks.model.entity.CandidateProcess;
import com.hyt.it.ogt.ks.model.vo.FileItemVO;
import com.hyt.it.ogt.ks.model.vo.paper.FileItemInfo;
import com.hyt.it.ogt.ks.model.vo.paper.FilePicAnswerVO;
import com.hyt.it.ogt.ks.model.vo.paper.PItemDTO;
import com.hyt.it.ogt.ks.service.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class FileItemServiceImpl implements IFileItemService {
    public static final String sep = ",";
    @Resource
    private IPaperService iPaperService;
    @Resource
    private ICandidateAnswerService iCandidateAnswerService;
    @Resource
    private ILogService iLogService;
    @Resource
    private ConfigManager configManager;
    @Resource
    private ICandidateProcessService iCandidateProcessService;
    @Resource
    private ExamInfoCacheService examInfoCacheService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(FileItemVO fileItemVO) {
        this.check(fileItemVO);
        if (fileItemVO.getFileList() != null && fileItemVO.getFileList().size() > 0) {
            CandidateAnswer itemAnswer = this.getItemAnswer(fileItemVO.getExamId(), fileItemVO.getCandidateId(),
                    fileItemVO.getPaperSort(), fileItemVO.getItemId());

            if (itemAnswer.getSubjectiveAnswer() != null) {
                int curr = itemAnswer.getSubjectiveAnswer().split(sep).length + fileItemVO.getFileList().size();
                int limit = this.getLimitByType(fileItemVO.getType());
                if (curr > limit) {
                    throw new KsBizRunTimeException(BizStatusCode.FILE_ANSWER_ITEM_UPLOAD_LIMIT.getCode(),
                            BizStatusCode.FILE_ANSWER_ITEM_UPLOAD_LIMIT.getMsg());
                }
            }
            List<String> fileList = new ArrayList<>();
            StringBuffer sb = new StringBuffer();
            if (StringUtils.isNotBlank(itemAnswer.getSubjectiveAnswer())) {
                String[] arr = itemAnswer.getSubjectiveAnswer().split(sep);
                for (String s : arr) {
                    if (StringUtils.isNotBlank(s)) {
                        fileList.add(s);
                    }
                }
            }
            fileList.addAll(fileItemVO.getFileList());
            int len = fileList.size();
            for (int i = 0; i < len; i++) {
                if (StringUtils.isNotBlank(fileList.get(i))) {
                    sb.append(fileList.get(i));
                    if (i < (len - 1)) {
                        sb.append(sep);
                    }
                }
            }
            CandidateAnswer updateEntity = new CandidateAnswer();
            updateEntity.setId(itemAnswer.getId());
            updateEntity.setSubjectiveAnswer(sb.toString());
            iCandidateAnswerService.updateById(updateEntity);

            CandidateLog log = CandidateLog.builder()
                    .id(UUIDUtils.randomUUID())
                    .examId(fileItemVO.getExamId())
                    .itemId(fileItemVO.getItemId())
                    .operateType(CandidateLogOperateType.SAVE_ITEM_ANSWER.getCode())
                    .operateContent(sb.toString())
                    .eventType(LogEventType.ANSWER_LOG.getCode()).operateType(CandidateAnswerLogType.ANSWER.getCode())
                    .candidateId(fileItemVO.getCandidateId())
                    .beginTime(LocalDateTime.now()).build();
            iLogService.saveAnswerLog(log);
        }
    }

    private void check(FileItemVO fileItemVO) {
        CandidateProcess one = iCandidateProcessService.lambdaQuery().select(CandidateProcess::getExamStatus)
                .eq(CandidateProcess::getExamId, fileItemVO.getExamId()).eq(CandidateProcess::getCandidateId, fileItemVO.getCandidateId())
                .eq(CandidateProcess::getDelFlag, false).one();
        if (one.getExamStatus() >= CandidateStatusCode.COMMIT.getCode()) {
            throw new KsBizRunTimeException(BizStatusCode.FILE_ANSWER_ITEM_UPLOAD_CANDIDATE_FINISH_EXAM.getCode(),
                    BizStatusCode.FILE_ANSWER_ITEM_UPLOAD_CANDIDATE_FINISH_EXAM.getMsg());
        }
    }

    @Override
    public FilePicAnswerVO get(String examId, String candidateId, Integer paperSort, String itemId) {
        CandidateAnswer itemAnswer = iPaperService.getItemAnswer(examId, candidateId, itemId, paperSort, TranslateLanguageCode.ZH.getCode());
        String subjectiveAnswer = itemAnswer.getSubjectiveAnswer();
        if (StringUtils.isBlank(subjectiveAnswer)) {
            return null;
        } else {
            String[] arr = subjectiveAnswer.split(sep);
            FilePicAnswerVO vo = new FilePicAnswerVO();
            vo.setItemType(itemAnswer.getItemType());
            vo.setChildIndex(itemAnswer.getItemMixSort());
            vo.setItemId(itemId);
            // 获取试卷
            CandidatePaper candidatePaper = iPaperService.getCandidatePaperFromCache(examId, candidateId, paperSort);
            // 从考务获取小题信息，如是复合题，则会把复合题下的子小题也查询过来
            PItemDTO item = iPaperService.getPItem(candidatePaper.getPaperId(), candidatePaper.getPaperVersion(), itemId);
            if(Objects.nonNull(item)){
                vo.setParentIndex(item.getTopicSort());
            }
            vo.setAddrs(Arrays.asList(arr));
            return vo;
        }
    }

    @SneakyThrows
    @Override
    public void del(String examId, String candidateId, Integer paperSort, String itemId, String fileUrl, HttpServletRequest request) {
        this.checkDelCondition(examId, candidateId);
        CandidateAnswer itemAnswer = iPaperService.getItemAnswer(examId, candidateId, itemId, paperSort, TranslateLanguageCode.ZH.getCode());
        String subjectiveAnswer = itemAnswer.getSubjectiveAnswer();
        if (StringUtils.isNotBlank(subjectiveAnswer)) {
            String[] arr = subjectiveAnswer.split(sep);
            URI uri = new URI(URLEncoder.encode(fileUrl));
            String source = uri.getPath();
            StringBuffer sb = new StringBuffer();
            List<String> list = new ArrayList<>();
            for (int i = 0; i < arr.length; i++) {
                URI uri2 = new URI(URLEncoder.encode(arr[i]));
                String target = uri2.getPath();
                if (!source.equalsIgnoreCase(target) && arr[i].startsWith("http")) {
                    list.add(arr[i]);
                }
            }
            for (int i = 0; i < list.size(); i++) {
                sb.append(list.get(i));
                if (i < (list.size() - 1)) {
                    sb.append(sep);
                }
            }
            CandidateAnswer updateEntity = new CandidateAnswer();
            updateEntity.setId(itemAnswer.getId());
            updateEntity.setSubjectiveAnswer(sb.toString());
            iCandidateAnswerService.updateById(updateEntity);

            CandidateLog log = CandidateLog.builder()
                    .id(UUIDUtils.randomUUID()).examId(examId).itemId(itemId).operateContent(sb.toString())
                    .eventType(LogEventType.ANSWER_LOG.getCode()).operateType(CandidateAnswerLogType.ANSWER.getCode())
                    .candidateId(candidateId).beginTime(LocalDateTime.now()).build();
            iLogService.saveAnswerLog(log);

        }
    }

    private void checkDelCondition(String examId, String candidateId) {
        CandidateProcess one = iCandidateProcessService.lambdaQuery().select(CandidateProcess::getExamStatus)
                .eq(CandidateProcess::getExamId, examId).eq(CandidateProcess::getCandidateId, candidateId)
                .eq(CandidateProcess::getDelFlag, false).one();
        if (one.getExamStatus() >= CandidateStatusCode.COMMIT.getCode()) {
            throw new KsBizRunTimeException(BizStatusCode.FILE_ANSWER_ITEM_DEL_CANDIDATE_FINISH_EXAM.getCode(),
                    BizStatusCode.FILE_ANSWER_ITEM_DEL_CANDIDATE_FINISH_EXAM.getMsg());
        }
    }

    @Override
    public FileItemInfo getItemInfo(String examId, String candidateId, Integer paperSort, String itemId) {
        PItemDTO item = iPaperService.getItemContent(examId, candidateId, itemId, paperSort, TranslateLanguageCode.ZH.getCode());
        CandidateAnswer itemAnswer = this.getItemAnswer(examId, candidateId, paperSort, itemId);
        FileItemInfo fileItemInfo = new FileItemInfo();
        fileItemInfo.setItemSort(itemAnswer.getItemMixSort());
        fileItemInfo.setItemContent(item.getItemContent());
        fileItemInfo.setTopicContent(item.getTopicName());
        fileItemInfo.setTopicSort(item.getTopicSort());
        ExamDTO examDTO = examInfoCacheService.getExamInfoFromCache(examId);
        if (Objects.nonNull(examDTO)) {
            Exam exam = examDTO.getExam();
            fileItemInfo.setExamName(exam.getExamName());
        }
        return fileItemInfo;
    }

    @Override
    public boolean allowUpload(String examId, String candidateId, Integer paperSort, String itemId, String type) {
        CandidateAnswer itemAnswer = this.getItemAnswer(examId, candidateId, paperSort, itemId);
        String subjectiveAnswer = itemAnswer.getSubjectiveAnswer();
        int limit = this.getLimitByType(type);
        if (StringUtils.isNotBlank(subjectiveAnswer) && subjectiveAnswer.split(sep).length >= limit) {
            return false;
        }
        return true;
    }

    @Override
    public int getLimitByType(String type) {
        // 默认5个
        int limit = 5;
        if (FileItemTypeCode.AUDIO.getCode().equalsIgnoreCase(type)) {
            limit = configManager.getAudioItemLimit();
        } else if (FileItemTypeCode.ATTACHMENT.getCode().equalsIgnoreCase(type)) {
            limit = configManager.getAttachmentItemLimit();
        } else if (FileItemTypeCode.AUDIO.getCode().equalsIgnoreCase(type)) {
            limit = configManager.getPictureItemLimit();
        }
        return limit;
    }

    @Override
    public int getFileMaxSizeByType(String type) {
        // 默认5个
        int maxSize = 10;
        if (FileItemTypeCode.AUDIO.getCode().equalsIgnoreCase(type)) {
            maxSize = configManager.getAudioItemMaxSize();
        } else if (FileItemTypeCode.ATTACHMENT.getCode().equalsIgnoreCase(type)) {
            maxSize = configManager.getAttachmentItemMaxSize();
        } else if (FileItemTypeCode.AUDIO.getCode().equalsIgnoreCase(type)) {
            maxSize = configManager.getPictureItemMaxSize();
        }
        return maxSize;
    }

    private CandidateAnswer getItemAnswer(String examId, String candidateId, Integer paperSort, String itemId) {
        CandidatePaper candidatePaper = iPaperService.getCandidatePaperFromCache(examId, candidateId, paperSort);
        CandidateAnswer answer = iCandidateAnswerService.lambdaQuery()
                .select(CandidateAnswer::getId, CandidateAnswer::getSubjectiveAnswer, CandidateAnswer::getItemMixSort)
                .eq(CandidateAnswer::getExamId, examId)
                .eq(CandidateAnswer::getCandidateId, candidateId)
                .eq(CandidateAnswer::getPaperId, candidatePaper.getPaperId())
                .eq(CandidateAnswer::getPaperVersion, candidatePaper.getPaperVersion())
                .eq(CandidateAnswer::getDelFlag, false)
                .eq(CandidateAnswer::getItemId, itemId).one();
        return answer;
    }
}
